<template>
  <div class="rich-text-editor" :class="{ 'fullscreen': isFullscreen, 'dark': isDarkMode }"  :style="{ height: editorHeight }">
    <div class="toolbar bg-gray-100 dark:bg-gray-800 p-2 rounded-t-md flex flex-wrap gap-2 border border-gray-300 dark:border-gray-700">
      <!-- Main toolbar -->
      <div class="toolbar-section flex flex-wrap gap-2">
        <!-- Text format buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in textFormatButtons"
            :key="button.command + (button.value || '')"
            @click="toggleCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700', { 'bg-gray-300 dark:bg-gray-600': isActive(button.command, button.value) }]"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- Text style buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in textStyleButtons"
            :key="button.command + (button.value || '')"
            @click="toggleCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700', { 'bg-gray-300 dark:bg-gray-600': isActive(button.command, button.value) }]"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- Alignment buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in alignmentButtons"
            :key="button.command"
            @click="toggleCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700', { 'bg-gray-300 dark:bg-gray-600': isActive(button.command, button.value) }]"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- List buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in listButtons"
            :key="button.command"
            @click="toggleCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700', { 'bg-gray-300 dark:bg-gray-600': isActive(button.command, button.value) }]"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- Indent/Outdent buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in indentButtons"
            :key="button.command"
            @click="executeCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700']"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>
      </div>

      <!-- Secondary toolbar (can be toggled on smaller screens) -->
      <div v-if="showAdvancedTools || !isMobile" class="toolbar-section flex flex-wrap gap-2 mt-2 md:mt-0">
        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1 hidden md:block"></div>

        <!-- Insert buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in insertButtons"
            :key="button.command + (button.value || '')"
            @click="executeCommand(button.command, button.value)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700']"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>

          <input
            type="file"
            ref="imageInput"
            accept="image/*"
            class="hidden"
            @change="handleImageUpload"
          />

          <input
            type="file"
            ref="videoInput"
            accept="video/*"
            class="hidden"
            @change="handleVideoUpload"
          />

          <input
            type="file"
            ref="fileInput"
            class="hidden"
            @change="handleFileUpload"
          />
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- Format selectors -->
        <div class="toolbar-group flex gap-1">
          <select
            class="toolbar-select px-2 py-1 rounded border border-gray-300 dark:border-gray-600 text-sm bg-white dark:bg-gray-700 dark:text-gray-200"
            @change="executeCommand('formatBlock', $event.target.value)"
            aria-label="Paragraph format"
          >
            <option value="">Paragraph</option>
            <option value="h1">Heading 1</option>
            <option value="h2">Heading 2</option>
            <option value="h3">Heading 3</option>
            <option value="h4">Heading 4</option>
            <option value="h5">Heading 5</option>
            <option value="h6">Heading 6</option>
            <option value="pre">Code Block</option>
            <option value="blockquote">Quote</option>
          </select>

          <select
            class="toolbar-select px-2 py-1 rounded border border-gray-300 dark:border-gray-600 text-sm bg-white dark:bg-gray-700 dark:text-gray-200"
            @change="executeCommand('fontName', $event.target.value)"
            aria-label="Font family"
          >
            <option value="Arial, sans-serif">Arial</option>
            <option value="'Times New Roman', serif">Times New Roman</option>
            <option value="'Courier New', monospace">Courier New</option>
            <option value="Georgia, serif">Georgia</option>
            <option value="Verdana, sans-serif">Verdana</option>
            <option value="'Trebuchet MS', sans-serif">Trebuchet MS</option>
            <option value="Impact, sans-serif">Impact</option>
            <option value="'Comic Sans MS', cursive">Comic Sans MS</option>
          </select>

          <select
            class="toolbar-select px-2 py-1 rounded border border-gray-300 dark:border-gray-600 text-sm bg-white dark:bg-gray-700 dark:text-gray-200"
            @change="executeCommand('fontSize', $event.target.value)"
            aria-label="Font size"
          >
            <option value="1">Small</option>
            <option value="2">Medium</option>
            <option value="3" selected>Normal</option>
            <option value="4">Large</option>
            <option value="5">X-Large</option>
            <option value="6">XX-Large</option>
            <option value="7">XXX-Large</option>
          </select>
        </div>

        <div class="toolbar-divider h-6 w-px bg-gray-300 dark:bg-gray-600 mx-1"></div>

        <!-- Color pickers -->
        <div class="toolbar-group flex gap-1 items-center">
          <div class="flex items-center gap-1">
            <span class="text-xs text-gray-500 dark:text-gray-400">Text:</span>
            <input
              type="color"
              class="w-6 h-6 rounded cursor-pointer"
              @change="executeCommand('foreColor', $event.target.value)"
              title="Text Color"
              aria-label="Text Color"
            />
          </div>

          <div class="flex items-center gap-1">
            <span class="text-xs text-gray-500 dark:text-gray-400">BG:</span>
            <input
              type="color"
              class="w-6 h-6 rounded cursor-pointer"
              @change="executeCommand('hiliteColor', $event.target.value)"
              title="Background Color"
              aria-label="Background Color"
            />
          </div>
        </div>
      </div>

      <!-- Utility toolbar (always visible) -->
      <div class="toolbar-section ml-auto flex gap-1">
        <!-- Search button -->
        <button
          @click="toggleSearch"
          class="toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700"
          :class="{ 'bg-gray-300 dark:bg-gray-600': showSearch }"
          title="Search and Replace"
          aria-label="Search and Replace"
        >
          <Search class="w-4 h-4" />
        </button>

        <!-- History buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            v-for="button in historyButtons"
            :key="button.command"
            @click="executeCommand(button.command)"
            :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700']"
            :title="button.title"
            :aria-label="button.title"
          >
            <component :is="button.icon" class="w-4 h-4" />
          </button>
        </div>

        <!-- Utility buttons -->
        <div class="toolbar-group flex gap-1">
          <button
            @click="toggleDarkMode"
            class="toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700"
            :title="isDarkMode ? 'Light Mode' : 'Dark Mode'"
            :aria-label="isDarkMode ? 'Light Mode' : 'Dark Mode'"
          >
            <component :is="isDarkMode ? Sun : Moon" class="w-4 h-4" />
          </button>

          <button
            @click="toggleAdvancedTools"
            class="toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700 md:hidden"
            :title="showAdvancedTools ? 'Hide Advanced Tools' : 'Show Advanced Tools'"
            :aria-label="showAdvancedTools ? 'Hide Advanced Tools' : 'Show Advanced Tools'"
          >
            <component :is="showAdvancedTools ? ChevronUp : ChevronDown" class="w-4 h-4" />
          </button>

          <button
            @click="toggleFullscreen"
            class="toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700"
            :title="isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'"
            :aria-label="isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'"
          >
            <component :is="isFullscreen ? Minimize2 : Maximize2" class="w-4 h-4" />
          </button>
        </div>
      </div>
    </div>

    <!-- Search and replace panel -->
    <div v-if="showSearch" class="search-panel p-2 border-x border-b border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 flex flex-wrap gap-2 items-center">
      <div class="flex items-center gap-2">
        <input
          type="text"
          v-model="searchText"
          placeholder="Search..."
          class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded text-sm bg-white dark:bg-gray-700 dark:text-gray-200"
          @keydown.enter="findText"
        />
        <button
          @click="findText"
          class="px-2 py-1 bg-blue-500 text-white rounded text-sm hover:bg-blue-600"
        >
          Find
        </button>
        <span class="text-xs text-gray-500 dark:text-gray-400" v-if="searchResults !== null">
          {{ searchResults === 0 ? 'No matches' : `${searchCurrentMatch} of ${searchResults}` }}
        </span>
      </div>

      <div class="flex items-center gap-2">
        <input
          type="text"
          v-model="replaceText"
          placeholder="Replace with..."
          class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded text-sm bg-white dark:bg-gray-700 dark:text-gray-200"
        />
        <button
          @click="replaceCurrentText"
          class="px-2 py-1 bg-blue-500 text-white rounded text-sm hover:bg-blue-600"
          :disabled="searchResults === 0 || searchResults === null"
        >
          Replace
        </button>
        <button
          @click="replaceAllText"
          class="px-2 py-1 bg-blue-500 text-white rounded text-sm hover:bg-blue-600"
          :disabled="searchResults === 0 || searchResults === null"
        >
          Replace All
        </button>
      </div>

      <div class="flex items-center gap-2 ml-auto">
        <button
          @click="findPrevious"
          class="px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded text-sm hover:bg-gray-300 dark:hover:bg-gray-600"
          :disabled="searchResults === 0 || searchResults === null"
        >
          Previous
        </button>
        <button
          @click="findNext"
          class="px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded text-sm hover:bg-gray-300 dark:hover:bg-gray-600"
          :disabled="searchResults === 0 || searchResults === null"
        >
          Next
        </button>
        <button
          @click="closeSearch"
          class="px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded text-sm hover:bg-gray-300 dark:hover:bg-gray-600"
        >
          Close
        </button>
      </div>
    </div>

    <!-- Editor content -->
    <div
      class="editor-content p-4 min-h-[250px] border border-t-0 border-gray-300 dark:border-gray-700 rounded-b-md focus:outline-none bg-white dark:bg-gray-900 dark:text-gray-100"
      contenteditable="true"
      ref="editorContent"
      @input="updateContent"
      @keydown="handleKeyDown"
      @mouseup="checkSelectionFormatting"
      @paste="handlePaste"
      @drop="handleDrop"
      @dragover="handleDragOver"
      :data-placeholder="placeholder"
      aria-multiline="true"
      role="textbox"
      :dir="textDirection"
    ></div>

    <!-- Floating toolbar for selected text -->
    <div
      v-if="showFloatingToolbar && props.allowFloatingToolbar"
      class="floating-toolbar absolute bg-white dark:bg-gray-800 shadow-lg rounded-md p-1 flex gap-1 border border-gray-300 dark:border-gray-700 z-10"
      :style="{ top: `${floatingToolbarPosition.top}px`, left: `${floatingToolbarPosition.left}px` }"
    >
      <button
        v-for="button in floatingToolbarButtons"
        :key="button.command + (button.value || '')"
        @click="toggleCommand(button.command, button.value)"
        :class="['toolbar-button p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700', { 'bg-gray-300 dark:bg-gray-600': isActive(button.command, button.value) }]"
        :title="button.title"
        :aria-label="button.title"
      >
        <component :is="button.icon" class="w-3 h-3" />
      </button>
    </div>

    <!-- Status bar -->
    <div class="status-bar mt-2 text-sm text-gray-500 dark:text-gray-400 flex flex-wrap justify-between items-center">
      <div class="flex gap-4">
        <span>Characters: {{ charCount }}</span>
        <span>Words: {{ wordCount }}</span>
        <span v-if="props.maxLength > 0" :class="{ 'text-red-500': charCount >= props.maxLength }">
          {{ charCount }}/{{ props.maxLength }}
        </span>
      </div>

      <div class="flex gap-2">
        <button
          @click="toggleTextDirection"
          class="text-xs px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600"
          :title="textDirection === 'rtl' ? 'Left-to-Right' : 'Right-to-Left'"
        >
          {{ textDirection === 'rtl' ? 'LTR' : 'RTL' }}
        </button>

        <div class="dropdown relative">
          <button
            @click="showExportOptions = !showExportOptions"
            class="text-xs px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600"
          >
            Export
          </button>
          <div
            v-if="showExportOptions"
            class="dropdown-menu absolute bottom-full right-0 mb-1 bg-white dark:bg-gray-800 shadow-lg rounded-md border border-gray-300 dark:border-gray-700 p-1 min-w-[120px]"
          >
            <button
              @click="exportContent('html')"
              class="block w-full text-left px-2 py-1 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
            >
              HTML
            </button>
            <button
              @click="exportContent('text')"
              class="block w-full text-left px-2 py-1 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
            >
              Plain Text
            </button>
            <button
              @click="exportContent('markdown')"
              class="block w-full text-left px-2 py-1 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
            >
              Markdown
            </button>
            <button
              @click="printContent"
              class="block w-full text-left px-2 py-1 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
            >
              Print
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- Special characters modal -->
    <div v-if="showSpecialChars" class="special-chars-modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="modal-content bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 max-w-2xl w-full max-h-[80vh] overflow-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-semibold dark:text-white">Special Characters</h3>
          <button @click="showSpecialChars = false" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
            <X class="w-5 h-5" />
          </button>
        </div>

        <div class="grid grid-cols-8 gap-2">
          <button
            v-for="char in specialCharacters"
            :key="char"
            @click="insertSpecialChar(char)"
            class="p-2 border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 text-center"
          >
            {{ char }}
          </button>
        </div>
      </div>
    </div>

    <!-- Table editing modal -->
    <div v-if="showTableEditor" class="table-editor-modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="modal-content bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 max-w-md w-full">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-semibold dark:text-white">Edit Table</h3>
          <button @click="showTableEditor = false" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
            <X class="w-5 h-5" />
          </button>
        </div>

        <div class="space-y-4">
          <div class="flex gap-4">
            <div class="flex-1">
              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Rows</label>
              <input
                type="number"
                v-model="tableRows"
                min="1"
                max="20"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 dark:text-white"
              />
            </div>
            <div class="flex-1">
              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Columns</label>
              <input
                type="number"
                v-model="tableCols"
                min="1"
                max="10"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 dark:text-white"
              />
            </div>
          </div>

          <div class="flex gap-4">
            <div class="flex-1">
              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Header</label>
              <select
                v-model="tableHeader"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 dark:text-white"
              >
                <option value="yes">Yes</option>
                <option value="no">No</option>
              </select>
            </div>
            <div class="flex-1">
              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Style</label>
              <select
                v-model="tableStyle"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 dark:text-white"
              >
                <option value="default">Default</option>
                <option value="striped">Striped</option>
                <option value="bordered">Bordered</option>
                <option value="compact">Compact</option>
              </select>
            </div>
          </div>

          <div class="flex justify-end gap-2 mt-4">
            <button
              @click="showTableEditor = false"
              class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
            >
              Cancel
            </button>
            <button
              @click="insertTableFromEditor"
              class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
            >
              Insert Table
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue';
import {
  Bold, Italic, Underline, Strikethrough, AlignLeft, AlignCenter, AlignRight, AlignJustify,
  List, ListOrdered, Link, Image, Undo, Redo, Code, Quote, Maximize2, Minimize2,
  Heading1, Heading2, Table, FileImage, Moon, Sun, ChevronDown, ChevronUp, Search,
  FileVideo, Paperclip, Indent, Outdent, Type, Eraser, Superscript, Subscript,
  SeparatorHorizontal, Hash, X, Printer, FileText, RotateCcw, RotateCw
} from 'lucide-vue-next';

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  placeholder: {
    type: String,
    default: 'Start typing...'
  },
  autofocus: {
    type: Boolean,
    default: false
  },
  maxLength: {
    type: Number,
    default: 0
  },
  initialDarkMode: {
    type: Boolean,
    default: false
  },
  allowFloatingToolbar: {
    type: Boolean,
    default: true
  },
  height: {
    type: String,
    default: '300px',
  },
});
const editorHeight = ref(props.height);
const emit = defineEmits(['update:modelValue', 'change', 'image-upload', 'file-upload', 'video-upload']);

// Refs
const editorContent = ref(null);
const imageInput = ref(null);
const videoInput = ref(null);
const fileInput = ref(null);
const content = ref(props.modelValue || '');
const isFullscreen = ref(false);
const isDarkMode = ref(props.initialDarkMode);
const savedSelection = ref(null);
const historyStack = ref({
  undo: [],
  redo: []
});

// UI state
const showAdvancedTools = ref(false);
const showSearch = ref(false);
const showFloatingToolbar = ref(false);
const floatingToolbarPosition = ref({ top: 0, left: 0 });
const showExportOptions = ref(false);
const showSpecialChars = ref(false);
const showTableEditor = ref(false);
const isMobile = ref(false);
const textDirection = ref('ltr');

// Search state
const searchText = ref('');
const replaceText = ref('');
const searchResults = ref(null);
const searchCurrentMatch = ref(0);

// Table editor state
const tableRows = ref(3);
const tableCols = ref(3);
const tableHeader = ref('yes');
const tableStyle = ref('default');

// Special characters
const specialCharacters = [
  '&', '©', '®', '™', '€', '£', '¥', '¢',
  '§', '¶', '†', '‡', '•', '·', '‣', '⁃',
  '–', '—', '…', '«', '»', '"', '\'', '"',
  '\'', '¡', '¿', '°', '±', '×', '÷', '≈',
  '≠', '≤', '≥', '∞', '∫', '∑', 'π', 'µ',
  'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ',
  'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π'
];

// Computed properties for stats
const charCount = computed(() => {
  // Remove HTML tags for accurate character count
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = content.value;
  return tempDiv.textContent.length;
});

const wordCount = computed(() => {
  // Remove HTML tags for accurate word count
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = content.value;
  const text = tempDiv.textContent || '';
  return text.split(/\s+/).filter(word => word.length > 0).length;
});

// Button groups
const textFormatButtons = [
  { icon: Bold, command: 'bold', title: 'Bold (Ctrl+B)' },
  { icon: Italic, command: 'italic', title: 'Italic (Ctrl+I)' },
  { icon: Underline, command: 'underline', title: 'Underline (Ctrl+U)' },
  { icon: Strikethrough, command: 'strikeThrough', title: 'Strikethrough' },
  { icon: Code, command: 'formatBlock', value: 'pre', title: 'Code Block' },
  { icon: Quote, command: 'formatBlock', value: 'blockquote', title: 'Quote' },
];

const textStyleButtons = [
  { icon: Superscript, command: 'superscript', title: 'Superscript' },
  { icon: Subscript, command: 'subscript', title: 'Subscript' },
  { icon: Eraser, command: 'removeFormat', title: 'Clear Formatting' },
];

const alignmentButtons = [
  { icon: AlignLeft, command: 'justifyLeft', title: 'Align Left' },
  { icon: AlignCenter, command: 'justifyCenter', title: 'Align Center' },
  { icon: AlignRight, command: 'justifyRight', title: 'Align Right' },
  { icon: AlignJustify, command: 'justifyFull', title: 'Justify' },
];

const listButtons = [
  { icon: List, command: 'insertUnorderedList', title: 'Bullet List' },
  { icon: ListOrdered, command: 'insertOrderedList', title: 'Numbered List' },
];

const indentButtons = [
  { icon: Indent, command: 'indent', title: 'Increase Indent' },
  { icon: Outdent, command: 'outdent', title: 'Decrease Indent' },
];

const insertButtons = [
  { icon: Link, command: 'createLink', title: 'Insert Link (Ctrl+K)' },
  { icon: Image, command: 'insertImage', title: 'Insert Image URL' },
  { icon: FileImage, command: 'uploadImage', title: 'Upload Image' },
  { icon: FileVideo, command: 'uploadVideo', title: 'Upload Video' },
  { icon: Paperclip, command: 'uploadFile', title: 'Upload File' },
  { icon: Table, command: 'showTableEditor', title: 'Insert Table' },
  { icon: SeparatorHorizontal, command: 'insertHorizontalRule', title: 'Insert Horizontal Line' },
  { icon: Hash, command: 'showSpecialChars', title: 'Special Characters' },
];

const historyButtons = [
  { icon: Undo, command: 'undo', title: 'Undo (Ctrl+Z)' },
  { icon: Redo, command: 'redo', title: 'Redo (Ctrl+Y)' },
];

const floatingToolbarButtons = [
  { icon: Bold, command: 'bold', title: 'Bold' },
  { icon: Italic, command: 'italic', title: 'Italic' },
  { icon: Underline, command: 'underline', title: 'Underline' },
  { icon: Strikethrough, command: 'strikeThrough', title: 'Strikethrough' },
  { icon: Link, command: 'createLink', title: 'Link' },
  { icon: Quote, command: 'formatBlock', value: 'blockquote', title: 'Quote' },
];

// 图片拉伸状态
const isResizing = ref(false);
const resizingImage = ref(null);
const startX = ref(0);
const startY = ref(0);
const startWidth = ref(0);
const startHeight = ref(0);

// Watch for external changes to modelValue
watch(() => props.modelValue, (newValue) => {
  if (newValue !== content.value) {
    content.value = newValue;
    if (editorContent.value) {
      editorContent.value.innerHTML = newValue;
    }
  }
});

// Check if device is mobile
const checkMobile = () => {
  isMobile.value = window.innerWidth < 768;
};

onMounted(() => {
  // Set initial content
  if (props.modelValue) {
    editorContent.value.innerHTML = props.modelValue;
  }

  // Set initial focus if autofocus is true
  if (props.autofocus) {
    editorContent.value.focus();
  }

  // Add mutation observer to track content changes
  const observer = new MutationObserver(() => {
    updateContent();
  });

  observer.observe(editorContent.value, {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true
  });

  // Add event listener for clicks on links
  editorContent.value.addEventListener('click', (e) => {
    if (e.target.tagName === 'A') {
      e.preventDefault();
      const href = e.target.getAttribute('href');
      if (confirm(`Open link: ${href}?`)) {
        window.open(href, '_blank');
      }
    }
  });

  // Initialize history stack with initial content
  addToHistory();

  // Set up polling for selection changes to update toolbar state
  setInterval(checkSelectionFormatting, 500);

  // Check if mobile
  checkMobile();
  window.addEventListener('resize', checkMobile);

  // Add click event listener to document to close dropdowns
  document.addEventListener('click', handleDocumentClick);

  // Add selection change event listener for floating toolbar
  document.addEventListener('selectionchange', handleSelectionChange);

  // 添加图片选择和调整大小的处理
  editorContent.value.addEventListener('click', (e) => {
    if (e.target.tagName === 'IMG') {
      // 选中图片时添加选中样式
      const allImages = editorContent.value.querySelectorAll('img');
      allImages.forEach(img => img.classList.remove('selected-image'));
      e.target.classList.add('selected-image');

      // 防止编辑器失去焦点
      setTimeout(() => {
        editorContent.value.focus();
      }, 0);
    } else {
      // 点击其他地方时移除选中样式
      const allImages = editorContent.value.querySelectorAll('img');
      allImages.forEach(img => img.classList.remove('selected-image'));
    }
  });

  // 为已有的图片添加拉伸功能
  const existingImages = editorContent.value.querySelectorAll('img');
  existingImages.forEach(img => {
    img.classList.add('resizable-image');
    img.setAttribute('contenteditable', 'false');
    img.addEventListener('mousedown', handleImageMouseDown);
    img.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();

      // 选中图片
      const allImages = editorContent.value.querySelectorAll('img');
      allImages.forEach(i => i.classList.remove('selected-image'));
      img.classList.add('selected-image');

      // 保持编辑器焦点
      setTimeout(() => {
        editorContent.value.focus();
      }, 0);
    });
  });
});

onBeforeUnmount(() => {
  // Clean up event listeners
  window.removeEventListener('resize', checkMobile);
  document.removeEventListener('click', handleDocumentClick);
  document.removeEventListener('selectionchange', handleSelectionChange);

  // 清理图片拉伸相关的事件监听器
  document.removeEventListener('mousemove', handleImageMouseMove);
  document.removeEventListener('mouseup', handleImageMouseUp);
});

// Handle document clicks to close dropdowns
const handleDocumentClick = (e) => {
  // Close export options dropdown if clicked outside
  if (showExportOptions.value && !e.target.closest('.dropdown')) {
    showExportOptions.value = false;
  }
};

// Handle selection change for floating toolbar
const handleSelectionChange = () => {
  if (!props.allowFloatingToolbar) return;

  const selection = window.getSelection();
  if (selection.rangeCount === 0 || selection.isCollapsed) {
    showFloatingToolbar.value = false;
    return;
  }

  // Check if selection is inside editor
  if (!isSelectionInEditor()) {
    showFloatingToolbar.value = false;
    return;
  }

  // Get selection position
  const range = selection.getRangeAt(0);
  const rect = range.getBoundingClientRect();

  // Position the floating toolbar above the selection
  floatingToolbarPosition.value = {
    top: rect.top - 40 + window.scrollY,
    left: rect.left + (rect.width / 2) - 75 // Center the toolbar
  };

  // Show the floating toolbar
  showFloatingToolbar.value = true;
};

// Save current selection
const saveSelection = () => {
  const selection = window.getSelection();
  if (selection.rangeCount > 0) {
    savedSelection.value = selection.getRangeAt(0).cloneRange();
  }
};

// Restore saved selection
const restoreSelection = () => {
  if (savedSelection.value) {
    const selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(savedSelection.value);
    return true;
  }
  return false;
};

// Add to history stack
const addToHistory = () => {
  // Don't add if content is the same as the last entry
  if (historyStack.value.undo.length > 0 &&
      historyStack.value.undo[historyStack.value.undo.length - 1] === editorContent.value.innerHTML) {
    return;
  }

  historyStack.value.undo.push(editorContent.value.innerHTML);
  // Clear redo stack when new changes are made
  historyStack.value.redo = [];

  // Limit history size
  if (historyStack.value.undo.length > 50) {
    historyStack.value.undo.shift();
  }
};

// Check if selection is inside editor
const isSelectionInEditor = () => {
  if (!editorContent.value) return false;

  const selection = window.getSelection();
  if (selection.rangeCount === 0) return false;

  const range = selection.getRangeAt(0);
  return editorContent.value.contains(range.commonAncestorContainer);
};
// Check formatting of current selection to update toolbar
const checkSelectionFormatting = () => {
  if (!isSelectionInEditor()) return;

  // Force UI update by triggering a small state change
  const temp = isFullscreen.value;
  isFullscreen.value = !temp;
  isFullscreen.value = temp;
};

// Toggle command - apply or remove formatting
const toggleCommand = (command, value = null) => {
  // Hide floating toolbar
  showFloatingToolbar.value = false;

  // Focus the editor first to ensure commands work
  editorContent.value.focus();

  // Save current selection
  saveSelection();

  // Save current state to history before executing command
  addToHistory();

  // Check if the command is already active
  const isCommandActive = isActive(command, value);

  // Handle special cases for different commands
  if (command === 'bold' || command === 'italic' || command === 'underline' || command === 'strikeThrough' ||
      command === 'superscript' || command === 'subscript') {
    // For basic formatting commands, we can use document.execCommand directly
    // The browser will toggle the state automatically
    restoreSelection();
    document.execCommand(command, false, value);
  } else if (command === 'justifyLeft' || command === 'justifyCenter' || command === 'justifyRight' || command === 'justifyFull') {
    // For alignment commands, we need to handle toggling manually
    restoreSelection();
    if (isCommandActive && command === 'justifyLeft') {
      // Don't toggle off justifyLeft as it's the default
      document.execCommand(command, false, value);
    } else if (isCommandActive) {
      // If active, reset to default (left align)
      document.execCommand('justifyLeft', false, null);
    } else {
      // If not active, apply the command
      document.execCommand(command, false, value);
    }
  } else if (command === 'insertUnorderedList' || command === 'insertOrderedList') {
    // For list commands, the browser handles toggling
    restoreSelection();
    document.execCommand(command, false, value);
  } else if (command === 'formatBlock') {
    // For block formatting, we need to handle toggling manually
    restoreSelection();
    if (isCommandActive) {
      // If active, reset to default (paragraph)
      document.execCommand('formatBlock', false, '<p>');
    } else {
      // If not active, apply the formatting
      document.execCommand(command, false, `<${value}>`);
    }
  } else {
    // For other commands, use the standard executeCommand function
    executeCommand(command, value);
  }

  // Restore focus to editor
  editorContent.value.focus();

  // Update content
  updateContent();
};

const executeCommand = (command, value = null) => {
  // Hide floating toolbar
  showFloatingToolbar.value = false;

  // Special commands that don't need editor focus
  if (command === 'showSpecialChars') {
    showSpecialChars.value = true;
    return;
  }

  if (command === 'showTableEditor') {
    showTableEditor.value = true;
    return;
  }

  // Focus the editor first to ensure commands work
  editorContent.value.focus();

  // Save current selection
  saveSelection();

  // Save current state to history before executing command
  addToHistory();

  // Handle special commands
  if (command === 'createLink') {
    const url = prompt('Enter URL:', 'https://');
    if (url) {
      restoreSelection();
      document.execCommand(command, false, url);

      // Make sure links open in new tab
      const selection = window.getSelection();
      const range = selection.getRangeAt(0);
      const links = editorContent.value.querySelectorAll('a');

      links.forEach(link => {
        if (range.intersectsNode(link)) {
          link.setAttribute('target', '_blank');
          link.setAttribute('rel', 'noopener noreferrer');
        }
      });
    }
    return;
  }

  if (command === 'insertImage') {
    const url = prompt('Enter image URL:', 'https://');
    if (url) {
      restoreSelection();
      document.execCommand(command, false, url);

      // Add alt text to image
      const selection = window.getSelection();
      const range = selection.getRangeAt(0);
      const images = editorContent.value.querySelectorAll('img');

      images.forEach(img => {
        if (range.intersectsNode(img)) {
          editorContent.value.blur();
          img.setAttribute('alt', 'Image');
          img.style.maxWidth = '100%';
          img.classList.add('resizable-image');
          img.setAttribute('contenteditable', 'false');

          // 添加自定义拖拽调整大小的事件处理
          img.addEventListener('mousedown', handleImageMouseDown);

          // 防止编辑器失去焦点
          img.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            // 选中图片
            const allImages = editorContent.value.querySelectorAll('img');
            allImages.forEach(i => i.classList.remove('selected-image'));
            img.classList.add('selected-image');

            // 保持编辑器焦点
            // setTimeout(() => {
            //   editorContent.value.focus();
            // }, 0);
          });
        }
      });
    }
    return;
  }

  if (command === 'uploadImage') {
    imageInput.value.click();
    return;
  }

  if (command === 'uploadVideo') {
    videoInput.value.click();
    return;
  }

  if (command === 'uploadFile') {
    fileInput.value.click();
    return;
  }

  if (command === 'formatBlock') {
    restoreSelection();
    document.execCommand(command, false, `<${value}>`);
    return;
  }

  if (command === 'undo') {
    if (historyStack.value.undo.length > 1) { // Keep at least one item in history
      // Save current state to redo stack
      historyStack.value.redo.push(historyStack.value.undo.pop());

      // Get previous state (now the last item in the stack)
      const previousState = historyStack.value.undo[historyStack.value.undo.length - 1];
      editorContent.value.innerHTML = previousState;
      updateContent();
    }
    return;
  }

  if (command === 'redo') {
    if (historyStack.value.redo.length > 0) {
      // Get next state
      const nextState = historyStack.value.redo.pop();

      // Add current state to undo stack
      historyStack.value.undo.push(nextState);

      // Apply the state
      editorContent.value.innerHTML = nextState;
      updateContent();
    }
    return;
  }

  // Execute regular command
  restoreSelection();
  document.execCommand(command, false, value);

  // Restore focus to editor
  editorContent.value.focus();

  // Update content
  updateContent();
};

const isActive = (command, value = null) => {
  try {
    if (command === 'formatBlock') {
      const currentValue = document.queryCommandValue('formatBlock');
      return currentValue === `<${value}>` || currentValue === value;
    }

    // Special case for strikeThrough - check both ways
    if (command === 'strikeThrough') {
      const selection = window.getSelection();
      if (selection.rangeCount === 0) return false;

      const range = selection.getRangeAt(0);
      const container = range.commonAncestorContainer;

      // Check if the selection is inside a strike element or has line-through style
      if (container.nodeType === Node.TEXT_NODE && container.parentNode) {
        const parent = container.parentNode;
        if (parent.tagName === 'STRIKE' || parent.tagName === 'S' ||
            (parent.style && parent.style.textDecoration &&
             parent.style.textDecoration.includes('line-through'))) {
          return true;
        }
      }
    }

    // Special case for underline - check both ways
    if (command === 'underline') {
      const selection = window.getSelection();
      if (selection.rangeCount === 0) return false;

      const range = selection.getRangeAt(0);
      const container = range.commonAncestorContainer;

      // Check if the selection is inside a u element or has underline style
      if (container.nodeType === Node.TEXT_NODE && container.parentNode) {
        const parent = container.parentNode;
        if (parent.tagName === 'U' ||
            (parent.style && parent.style.textDecoration &&
             parent.style.textDecoration.includes('underline'))) {
          return true;
        }
      }
    }

    return document.queryCommandState(command);
  } catch (e) {
    console.error('Error checking command state:', e);
    return false;
  }
};

const updateContent = () => {
  // Only update if content has changed
  if (content.value !== editorContent.value.innerHTML) {
    content.value = editorContent.value.innerHTML;
    emit('update:modelValue', content.value);
    emit('change', content.value);
  }
};

const handleKeyDown = (e) => {
  // Check max length if set
  if (props.maxLength > 0 && charCount.value >= props.maxLength &&
      !e.ctrlKey && !e.metaKey &&
      e.key !== 'Backspace' && e.key !== 'Delete' &&
      e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' &&
      e.key !== 'ArrowUp' && e.key !== 'ArrowDown') {
    e.preventDefault();
    return;
  }

  // Handle keyboard shortcuts
  if (e.ctrlKey || e.metaKey) {
    switch (e.key.toLowerCase()) {
      case 'b':
        e.preventDefault();
        toggleCommand('bold');
        break;
      case 'i':
        e.preventDefault();
        toggleCommand('italic');
        break;
      case 'u':
        e.preventDefault();
        toggleCommand('underline');
        break;
      case 'k':
        e.preventDefault();
        executeCommand('createLink');
        break;
      case 'f':
        e.preventDefault();
        toggleSearch();
        break;
      case 'z':
        e.preventDefault();
        if (e.shiftKey) {
          executeCommand('redo');
        } else {
          executeCommand('undo');
        }
        break;
      case 'y':
        e.preventDefault();
        executeCommand('redo');
        break;
      case 'p':
        if (e.shiftKey) {
          e.preventDefault();
          printContent();
        }
        break;
    }
  }

  // Add to history on space, enter, delete, backspace
  if (['Space', 'Enter', 'Delete', 'Backspace'].includes(e.code)) {
    setTimeout(() => {
      addToHistory();
    }, 10);
  }

  // Close search on escape
  if (e.key === 'Escape' && showSearch.value) {
    closeSearch();
  }
};

const handlePaste = (e) => {
  // Prevent default paste behavior
  e.preventDefault();

  // Get plain text from clipboard
  const text = (e.clipboardData || window.clipboardData).getData('text/plain');

  // Insert text at cursor position
  document.execCommand('insertText', false, text);

  // Add to history after paste
  setTimeout(() => {
    addToHistory();
  }, 10);
};

const handleDragOver = (e) => {
  e.preventDefault();
  e.stopPropagation();
  editorContent.value.classList.add('drag-over');
};

const handleDrop = (e) => {
  e.preventDefault();
  e.stopPropagation();

  editorContent.value.classList.remove('drag-over');

  // Get dropped files
  const files = e.dataTransfer.files;
  if (files.length === 0) return;

  // Handle the first file
  const file = files[0];

  // Save current selection
  saveSelection();

  // Handle different file types
  if (file.type.startsWith('image/')) {
    handleImageFile(file);
  } else if (file.type.startsWith('video/')) {
    handleVideoFile(file);
  } else {
    handleGenericFile(file);
  }
};

// 处理图片鼠标按下事件
const handleImageMouseDown = (e) => {
  editorContent.value.blur();
  const img = e.target;
  if (img.tagName === 'IMG') {
    e.preventDefault();
      }
  // 检查是否点击了调整大小的手柄（右下角区域）
  const rect = img.getBoundingClientRect();
  const isHandle = e.clientX > rect.right - 15 && e.clientY > rect.bottom - 15;

  if (isHandle) {
    e.preventDefault();
    e.stopPropagation();

    isResizing.value = true;
    resizingImage.value = img;
    startX.value = e.clientX;
    startY.value = e.clientY;
    startWidth.value = img.offsetWidth;
    startHeight.value = img.offsetHeight;

    // 添加调整大小时的类
    img.classList.add('resizable-image-resizing');

    // 添加鼠标移动和松开事件
    document.addEventListener('mousemove', handleImageMouseMove);
    document.addEventListener('mouseup', handleImageMouseUp);

    // 设置调整大小时的光标样式
    document.body.style.cursor = 'nwse-resize';
  }
};

// 处理图片鼠标移动事件
const handleImageMouseMove = (e) => {
  if (!isResizing.value || !resizingImage.value) return;

  e.preventDefault();

  const deltaX = e.clientX - startX.value;
  const deltaY = e.clientY - startY.value;

  // 计算新的宽高
  const newWidth = Math.max(50, startWidth.value + deltaX);
  const newHeight = Math.max(30, startHeight.value + deltaY);

  // 应用新的宽高
  resizingImage.value.style.width = `${newWidth}px`;
  resizingImage.value.style.height = `${newHeight}px`;

  // 更新内容
  updateContent();
};

// 处理图片鼠标松开事件
const handleImageMouseUp = (e) => {
  if (isResizing.value) {
    e.preventDefault();

    isResizing.value = false;

    // 移除调整大小时的类
    if (resizingImage.value) {
      resizingImage.value.classList.remove('resizable-image-resizing');
      resizingImage.value = null;
    }

    // 移除鼠标移动和松开事件
    document.removeEventListener('mousemove', handleImageMouseMove);
    document.removeEventListener('mouseup', handleImageMouseUp);

    // 恢复光标样式
    document.body.style.cursor = '';

    // 添加到历史记录
    addToHistory();
  }
};

const handleImageUpload = (e) => {
  const file = e.target.files[0];
  if (file) {
    // Validate file type
    if (!file.type.startsWith('image/')) {
      alert('Please select an image file.');
      imageInput.value.value = '';
      return;
    }

    // Validate file size (max 5MB)
    if (file.size > 5 * 1024 * 1024) {
      alert('Image size should be less than 5MB.');
      imageInput.value.value = '';
      return;
    }

    handleImageFile(file);

    // Reset file input
    imageInput.value.value = '';
  }
};

const handleVideoUpload = (e) => {
  const file = e.target.files[0];
  if (file) {
    // Validate file type
    if (!file.type.startsWith('video/')) {
      alert('Please select a video file.');
      videoInput.value.value = '';
      return;
    }

    // Validate file size (max 50MB)
    if (file.size > 50 * 1024 * 1024) {
      alert('Video size should be less than 50MB.');
      videoInput.value.value = '';
      return;
    }

    handleVideoFile(file);

    // Reset file input
    videoInput.value.value = '';
  }
};

const handleFileUpload = (e) => {
  const file = e.target.files[0];
  if (file) {
    // Validate file size (max 10MB)
    if (file.size > 10 * 1024 * 1024) {
      alert('File size should be less than 10MB.');
      fileInput.value.value = '';
      return;
    }

    handleGenericFile(file);

    // Reset file input
    fileInput.value.value = '';
  }
};

const handleImageFile = (file) => {
  const reader = new FileReader();
  reader.onload = (event) => {
    if (restoreSelection()) {
      document.execCommand('insertImage', false, event.target.result);

      // Add alt text and style to image
      const selection = window.getSelection();
      const range = selection.getRangeAt(0);
      const images = editorContent.value.querySelectorAll('img');

      images.forEach(img => {
        if (range.intersectsNode(img)) {
          img.setAttribute('alt', file.name.replace(/\.[^/.]+$/, ""));
          img.style.maxWidth = '100%';
          img.classList.add('resizable-image');

          // 使图片可拖拽调整大小
          img.setAttribute('contenteditable', 'false');

          // 添加自定义拖拽调整大小的事件处理
          img.addEventListener('mousedown', handleImageMouseDown);

          // 防止编辑器失去焦点
          img.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            // 选中图片
            const allImages = editorContent.value.querySelectorAll('img');
            allImages.forEach(i => i.classList.remove('selected-image'));
            img.classList.add('selected-image');

            // 保持编辑器焦点
            setTimeout(() => {
              editorContent.value.focus();
            }, 0);
          });
        }
      });

      // Add to history after image upload
      setTimeout(() => {
        addToHistory();
      }, 10);

      // Emit image upload event
      emit('image-upload', {
        file,
        dataUrl: event.target.result
      });
    }
  };
  reader.readAsDataURL(file);
};

const handleVideoFile = (file) => {
  const reader = new FileReader();
  reader.onload = (event) => {
    if (restoreSelection()) {
      // Create video element
      const videoHTML = `
        <video controls style="max-width: 100%; height: auto;" class="editor-video">
          <source src="${event.target.result}" type="${file.type}">
          Your browser does not support the video tag.
        </video>
      `;

      document.execCommand('insertHTML', false, videoHTML);

      // Add to history after video upload
      setTimeout(() => {
        addToHistory();
      }, 10);

      // Emit video upload event
      emit('video-upload', {
        file,
        dataUrl: event.target.result
      });
    }
  };
  reader.readAsDataURL(file);
};

const handleGenericFile = (file) => {
  if (restoreSelection()) {
    // Create file link
    const fileHTML = `
      <div class="file-attachment">
        <a href="#" class="file-link" data-filename="${file.name}" data-size="${file.size}">
          📎 ${file.name} (${formatFileSize(file.size)})
        </a>
      </div>
    `;

    document.execCommand('insertHTML', false, fileHTML);

    // Add to history after file upload
    setTimeout(() => {
      addToHistory();
    }, 10);

    // Emit file upload event
    emit('file-upload', { file });
  }
};

const formatFileSize = (bytes) => {
  if (bytes < 1024) return bytes + ' B';
  else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
  else return (bytes / 1048576).toFixed(1) + ' MB';
};

const insertTableFromEditor = () => {
  showTableEditor.value = false;

  if (restoreSelection()) {
    insertTable(tableRows.value, tableCols.value, tableHeader.value === 'yes', tableStyle.value);
  }
};

const insertTable = (rows, cols, hasHeader = true, style = 'default') => {
  let tableClasses = 'editor-table';

  // Add style classes
  if (style === 'striped') {
    tableClasses += ' table-striped';
  } else if (style === 'bordered') {
    tableClasses += ' table-bordered';
  } else if (style === 'compact') {
    tableClasses += ' table-compact';
  }

  let tableHTML = `<table class="${tableClasses}" style="width:100%; border-collapse: collapse;">`;

  // Create header row if needed
  if (hasHeader) {
    tableHTML += '<thead><tr>';
    for (let i = 0; i < cols; i++) {
      tableHTML += `<th style="border: 1px solid #ccc; padding: 8px; text-align: left;">Header ${i+1}</th>`;
    }
    tableHTML += '</tr></thead>';
  }

  // Create body rows
  tableHTML += '<tbody>';
  for (let i = 0; i < (hasHeader ? rows - 1 : rows); i++) {
    tableHTML += '<tr>';
    for (let j = 0; j < cols; j++) {
      tableHTML += `<td style="border: 1px solid #ccc; padding: 8px;">Cell ${i+1}-${j+1}</td>`;
    }
    tableHTML += '</tr>';
  }

  tableHTML += '</tbody></table><p></p>';

  document.execCommand('insertHTML', false, tableHTML);

  // Add to history after table insertion
  setTimeout(() => {
    addToHistory();
  }, 10);
};

const insertSpecialChar = (char) => {
  showSpecialChars.value = false;

  if (restoreSelection()) {
    document.execCommand('insertText', false, char);
  }
};

const toggleFullscreen = () => {
  isFullscreen.value = !isFullscreen.value;

  if (isFullscreen.value) {
    document.body.style.overflow = 'hidden';
  } else {
    document.body.style.overflow = '';
  }

  // Focus editor after toggling fullscreen
  setTimeout(() => {
    editorContent.value.focus();
  }, 100);
};

const toggleDarkMode = () => {
  isDarkMode.value = !isDarkMode.value;
};

const toggleAdvancedTools = () => {
  showAdvancedTools.value = !showAdvancedTools.value;
};

const toggleSearch = () => {
  showSearch.value = !showSearch.value;
  searchResults.value = null;

  if (showSearch.value) {
    // Focus search input after a short delay
    setTimeout(() => {
      document.querySelector('.search-panel input[type="text"]').focus();
    }, 100);
  }
};

const closeSearch = () => {
  showSearch.value = false;
  // Remove any search highlights
  const content = editorContent.value.innerHTML;
  editorContent.value.innerHTML = content.replace(/<mark class="search-highlight">(.*?)<\/mark>/g, '$1');
};

const findText = () => {
  if (!searchText.value) return;

  // Remove previous highlights
  const content = editorContent.value.innerHTML;
  editorContent.value.innerHTML = content.replace(/<mark class="search-highlight">(.*?)<\/mark>/g, '$1');

  // Create a text node of the content
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = editorContent.value.innerHTML;
  const textContent = tempDiv.textContent;

  // Find all occurrences
  const searchRegex = new RegExp(escapeRegExp(searchText.value), 'gi');
  const matches = textContent.match(searchRegex);

  if (!matches) {
    searchResults.value = 0;
    searchCurrentMatch.value = 0;
    return;
  }

  searchResults.value = matches.length;
  searchCurrentMatch.value = 1;

  // Highlight the first occurrence
  highlightOccurrence(0);
};

const findNext = () => {
  if (searchCurrentMatch.value < searchResults.value) {
    searchCurrentMatch.value++;
  } else {
    searchCurrentMatch.value = 1; // Wrap around to the first match
  }

  highlightOccurrence(searchCurrentMatch.value - 1);
};

const findPrevious = () => {
  if (searchCurrentMatch.value > 1) {
    searchCurrentMatch.value--;
  } else {
    searchCurrentMatch.value = searchResults.value; // Wrap around to the last match
  }

  highlightOccurrence(searchCurrentMatch.value - 1);
};

const highlightOccurrence = (index) => {
  // Remove previous highlights
  const content = editorContent.value.innerHTML;
  editorContent.value.innerHTML = content.replace(/<mark class="search-highlight">(.*?)<\/mark>/g, '$1');

  // Find the text node containing the occurrence
  const walker = document.createTreeWalker(
    editorContent.value,
    NodeFilter.SHOW_TEXT,
    null,
    false
  );

  const searchRegex = new RegExp(escapeRegExp(searchText.value), 'gi');
  let currentIndex = 0;
  let node;

  // Find the node containing the occurrence
  while (node = walker.nextNode()) {
    const matches = node.textContent.match(searchRegex);
    if (matches) {
      if (currentIndex + matches.length > index) {
        // This node contains our target occurrence
        const occurrenceIndex = index - currentIndex;
        const nodeText = node.textContent;

        // Find the position of the occurrence in this node
        searchRegex.lastIndex = 0;
        let matchIndex;
        let i = 0;

        while ((matchIndex = searchRegex.exec(nodeText)) !== null) {
          if (i === occurrenceIndex) {
            // Create a range for the match
            const range = document.createRange();
            range.setStart(node, matchIndex.index);
            range.setEnd(node, matchIndex.index + matchIndex[0].length);

            // Create a mark element
            const mark = document.createElement('mark');
            mark.className = 'search-highlight';

            // Wrap the match with the mark
            range.surroundContents(mark);

            // Scroll the mark into view
            mark.scrollIntoView({ behavior: 'smooth', block: 'center' });

            // Break out of the loop
            return;
          }
          i++;
        }
      }
      currentIndex += matches.length;
    }
  }
};

const replaceCurrentText = () => {
  if (!searchText.value) return;

  // Get the current highlighted match
  const mark = editorContent.value.querySelector('mark.search-highlight');
  if (!mark) return;

  // Replace the text
  mark.textContent = replaceText.value;

  // Remove the highlight
  const parent = mark.parentNode;
  while (mark.firstChild) {
    parent.insertBefore(mark.firstChild, mark);
  }
  parent.removeChild(mark);

  // Update content
  updateContent();

  // Find next occurrence
  findNext();
};

const replaceAllText = () => {
  if (!searchText.value) return;

  // Replace all occurrences
  const content = editorContent.value.innerHTML;
  const searchRegex = new RegExp(escapeRegExp(searchText.value), 'g');
  editorContent.value.innerHTML = content.replace(searchRegex, replaceText.value);

  // Update content
  updateContent();

  // Reset search
  searchResults.value = 0;
  searchCurrentMatch.value = 0;
};

const escapeRegExp = (string) => {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};

const toggleTextDirection = () => {
  textDirection.value = textDirection.value === 'ltr' ? 'rtl' : 'ltr';
};

const exportContent = (format) => {
  showExportOptions.value = false;

  let content = '';

  if (format === 'html') {
    content = editorContent.value.innerHTML;
    downloadFile(content, 'document.html', 'text/html');
  } else if (format === 'text') {
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = editorContent.value.innerHTML;
    content = tempDiv.textContent;
    downloadFile(content, 'document.txt', 'text/plain');
  } else if (format === 'markdown') {
    content = htmlToMarkdown(editorContent.value.innerHTML);
    downloadFile(content, 'document.md', 'text/markdown');
  }
};

const htmlToMarkdown = (html) => {
  // This is a simple conversion, a full implementation would be more complex
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = html;

  // Replace headings
  const headings = tempDiv.querySelectorAll('h1, h2, h3, h4, h5, h6');
  headings.forEach(heading => {
    const level = heading.tagName.charAt(1);
    const text = heading.textContent;
    const markdown = '#'.repeat(parseInt(level)) + ' ' + text;
    const p = document.createElement('p');
    p.textContent = markdown;
    heading.parentNode.replaceChild(p, heading);
  });

  // Replace bold
  const bolds = tempDiv.querySelectorAll('b, strong');
  bolds.forEach(bold => {
    const text = bold.textContent;
    const markdown = `**${text}**`;
    const textNode = document.createTextNode(markdown);
    bold.parentNode.replaceChild(textNode, bold);
  });

  // Replace italic
  const italics = tempDiv.querySelectorAll('i, em');
  italics.forEach(italic => {
    const text = italic.textContent;
    const markdown = `*${text}*`;
    const textNode = document.createTextNode(markdown);
    italic.parentNode.replaceChild(textNode, italic);
  });

  // Replace links
  const links = tempDiv.querySelectorAll('a');
  links.forEach(link => {
    const text = link.textContent;
    const href = link.getAttribute('href');
    const markdown = `[${text}](${href})`;
    const textNode = document.createTextNode(markdown);
    link.parentNode.replaceChild(textNode, link);
  });

  // Replace images
  const images = tempDiv.querySelectorAll('img');
  images.forEach(image => {
    const alt = image.getAttribute('alt') || '';
    const src = image.getAttribute('src');
    const markdown = `![${alt}](${src})`;
    const textNode = document.createTextNode(markdown);
    image.parentNode.replaceChild(textNode, image);
  });

  // Replace lists
  const uls = tempDiv.querySelectorAll('ul');
  uls.forEach(ul => {
    const items = ul.querySelectorAll('li');
    const listItems = Array.from(items).map(item => `- ${item.textContent}`).join('\n');
    const p = document.createElement('p');
    p.textContent = listItems;
    ul.parentNode.replaceChild(p, ul);
  });

  const ols = tempDiv.querySelectorAll('ol');
  ols.forEach(ol => {
    const items = ol.querySelectorAll('li');
    const listItems = Array.from(items).map((item, index) => `${index + 1}. ${item.textContent}`).join('\n');
    const p = document.createElement('p');
    p.textContent = listItems;
    ol.parentNode.replaceChild(p, ol);
  });

  // Replace blockquotes
  const blockquotes = tempDiv.querySelectorAll('blockquote');
  blockquotes.forEach(blockquote => {
    const text = blockquote.textContent;
    const lines = text.split('\n').map(line => `> ${line}`).join('\n');
    const p = document.createElement('p');
    p.textContent = lines;
    blockquote.parentNode.replaceChild(p, blockquote);
  });

  return tempDiv.textContent;
};

const downloadFile = (content, filename, contentType) => {
  const blob = new Blob([content], { type: contentType });
  const url = URL.createObjectURL(blob);

  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();

  URL.revokeObjectURL(url);
};

const printContent = () => {
  showExportOptions.value = false;

  const printWindow = window.open('', '_blank');
  printWindow.document.write(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>Print Document</title>
      <style>
        body {
          font-family: Arial, sans-serif;
          line-height: 1.6;
          margin: 2cm;
        }
        img {
          max-width: 100%;
        }
        table {
          border-collapse: collapse;
          width: 100%;
        }
        th, td {
          border: 1px solid #ddd;
          padding: 8px;
        }
        th {
          background-color: #f2f2f2;
        }
        @media print {
          @page {
            margin: 2cm;
          }
        }
      </style>
    </head>
    <body>
      ${editorContent.value.innerHTML}
      <script>
        // Use a self-invoking function to avoid conflicts
        (function() {
          window.onload = function() {
            window.print();
            window.setTimeout(function() {
              window.close();
            }, 500);
          };
        })();
      <\/script> <!-- Escape the closing script tag -->
    </body>
    </html>
  `);
  printWindow.document.close();
};

// Custom methods for direct formatting
const applyInlineStyle = (tagName) => {
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return;

  const range = selection.getRangeAt(0);
  const element = document.createElement(tagName);
  element.appendChild(range.extractContents());
  range.insertNode(element);

  // Update selection
  selection.removeAllRanges();
  selection.addRange(range);

  // Update content
  updateContent();
};

// Expose methods and content for parent components
defineExpose({
  getContent: () => content.value,
  setContent: (html) => {
    if (editorContent.value) {
      editorContent.value.innerHTML = html;
      content.value = html;
      emit('update:modelValue', content.value);

      // Reset history when content is set externally
      historyStack.value = {
        undo: [html],
        redo: []
      };
    }
  },
  clearContent: () => {
    if (editorContent.value) {
      editorContent.value.innerHTML = '';
      content.value = '';
      emit('update:modelValue', '');

      // Reset history when content is cleared
      historyStack.value = {
        undo: [''],
        redo: []
      };
    }
  },
  focus: () => {
    editorContent.value?.focus();
  },
  // Direct formatting methods
  applyBold: () => toggleCommand('bold'),
  applyItalic: () => toggleCommand('italic'),
  applyUnderline: () => toggleCommand('underline'),
  applyStrikethrough: () => toggleCommand('strikeThrough'),
  // Export methods
  exportHtml: () => exportContent('html'),
  exportText: () => exportContent('text'),
  exportMarkdown: () => exportContent('markdown'),
  print: () => printContent(),
  // Search methods
  search: (text) => {
    searchText.value = text;
    showSearch.value = true;
    findText();
  }
});
</script>

<style scoped>
.rich-text-editor {
  width: 100%;
  transition: all 0.3s ease;
}

.rich-text-editor.fullscreen {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  background: white;
  padding: 1rem;
}

.rich-text-editor.fullscreen .editor-content {
  height: calc(100vh - 200px);
  max-height: none;
}

.toolbar-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  transition: all 0.2s ease;
}

.toolbar-button:hover {
  transform: translateY(-1px);
}

.editor-content {
  overflow-y: auto;
  max-height: 500px;
  transition: all 0.2s ease;
}

.editor-content:focus {
  outline: 2px solid #d1d5db;
}

.editor-content.dark:focus {
  outline: 2px solid #4b5563;
}

.editor-content:empty:before {
  content: attr(data-placeholder);
  color: #9ca3af;
  pointer-events: none;
}

.editor-content.drag-over {
  background-color: rgba(59, 130, 246, 0.1);
  outline: 2px dashed #3b82f6;
}

/* Style for blockquote */
.editor-content blockquote {
  border-left: 3px solid #d1d5db;
  padding-left: 1rem;
  margin-left: 0;
  color: #6b7280;
}

.dark .editor-content blockquote {
  border-left-color: #4b5563;
  color: #9ca3af;
}

/* Style for headings */
.editor-content h1 {
  font-size: 1.5rem;
  font-weight: bold;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.editor-content h2 {
  font-size: 1.25rem;
  font-weight: bold;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.editor-content h3 {
  font-size: 1.125rem;
  font-weight: bold;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.editor-content h4 {
  font-size: 1rem;
  font-weight: bold;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.editor-content h5, .editor-content h6 {
  font-weight: bold;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

/* Style for code blocks */
.editor-content pre {
  background-color: #f3f4f6;
  padding: 0.5rem;
  border-radius: 0.25rem;
  font-family: monospace;
  white-space: pre-wrap;
}

.dark .editor-content pre {
  background-color: #374151;
}

/* Style for links */
.editor-content a {
  color: #3b82f6;
  text-decoration: underline;
}

.dark .editor-content a {
  color: #60a5fa;
}

/* Style for tables */
.editor-content table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 1rem;
}

.editor-content th,
.editor-content td {
  border: 1px solid #d1d5db;
  padding: 0.5rem;
}

.dark .editor-content th,
.dark .editor-content td {
  border-color: #4b5563;
}

.editor-content th {
  background-color: #f3f4f6;
  font-weight: bold;
}

.dark .editor-content th {
  background-color: #374151;
}

/* Table styles */
.editor-table.table-striped tr:nth-child(even) {
  background-color: #f9fafb;
}

.dark .editor-table.table-striped tr:nth-child(even) {
  background-color: #1f2937;
}

.editor-table.table-bordered th,
.editor-table.table-bordered td {
  border-width: 2px;
}

.editor-table.table-compact th,
.editor-table.table-compact td {
  padding: 0.25rem;
}

/* Style for underline and strikethrough */
.editor-content u {
  text-decoration: underline;
}

.editor-content s,
.editor-content strike {
  text-decoration: line-through;
}

/* Style for horizontal rule */
.editor-content hr {
  border: none;
  border-top: 1px solid #d1d5db;
  margin: 1rem 0;
}

.dark .editor-content hr {
  border-top-color: #4b5563;
}

/* Style for file attachments */
.editor-content .file-attachment {
  display: inline-block;
  margin: 0.5rem 0;
  padding: 0.5rem;
  background-color: #f3f4f6;
  border-radius: 0.25rem;
}

.dark .editor-content .file-attachment {
  background-color: #374151;
}

.editor-content .file-link {
  display: flex;
  align-items: center;
  color: #3b82f6;
  text-decoration: none;
}

.dark .editor-content .file-link {
  color: #60a5fa;
}

/* Style for videos */
.editor-content .editor-video {
  max-width: 100%;
  height: auto;
  margin: 0.5rem 0;
}

/* Style for resizable images */
.editor-content .resizable-image {
  max-width: 100%;
  height: auto;
  margin: 0.5rem 0;
  border: 1px solid transparent;
  display: inline-block;
  box-sizing: border-box;
  min-width: 50px;
  min-height: 30px;
  position: relative; /* 添加相对定位 */
  cursor: default; /* 默认光标 */
}

.editor-content .resizable-image::after {
  content: '';
  position: absolute;
  right: -5px;
  bottom: -5px;
  width: 10px;
  height: 10px;
  background-color: #3b82f6;
  border: 2px solid white;
  border-radius: 2px;
  cursor: nwse-resize !important;
  z-index: 10;
}

.dark .editor-content .resizable-image::after {
  border-color: #1f2937;
}

.editor-content .resizable-image:hover {
  border-color: #d1d5db;
}

.editor-content .resizable-image-resizing {
  user-select: none;
  pointer-events: none;
}

/* 添加选中图片的样式 */
.editor-content .selected-image {
  border: 2px solid #3b82f6 !important;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
}

.dark .editor-content .selected-image {
  border-color: #60a5fa !important;
  box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.5);
}

/* Responsive adjustments */
@media (max-width: 640px) {
  .toolbar {
    flex-wrap: wrap;
  }

  .toolbar-divider {
    display: none;
  }

  .toolbar-group {
    margin-bottom: 0.5rem;
  }

  .search-panel {
    flex-direction: column;
    align-items: flex-start;
  }

  .search-panel > div {
    margin-bottom: 0.5rem;
    width: 100%;
  }
}
button{
  border:none;
}
</style>
